{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using the Fixed Variance process\n",
    "The `FixedVariance` volatility process can be used to implement zig-zag model \n",
    "estimation where two steps are repeated until convergence.  This can be used \n",
    "to estimate models which may not be easy to estimate as a single process due\n",
    "to numerical issues or a high-dimensional parameter space."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "_This setup code is required to run in an IPython notebook_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import seaborn\n",
    "\n",
    "seaborn.set_style(\"darkgrid\")\n",
    "plt.rc(\"figure\", figsize=(16, 6))\n",
    "plt.rc(\"savefig\", dpi=90)\n",
    "plt.rc(\"font\", family=\"sans-serif\")\n",
    "plt.rc(\"font\", size=14)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setup\n",
    "\n",
    "Imports used in this example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data\n",
    "The VIX index will be used to illustrate the use of the `FixedVariance` process.  The data is from FRED and is provided by the `arch` package."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import arch.data.vix\n",
    "\n",
    "vix_data = arch.data.vix.load()\n",
    "vix = vix_data.vix.dropna()\n",
    "vix.name = \"VIX Index\"\n",
    "ax = vix.plot(title=\"VIX Index\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initial Mean Model Estimation\n",
    "The first step is to estimate the mean to filter the residuals using a constant variance. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from arch.univariate.mean import HARX, ZeroMean\n",
    "from arch.univariate.volatility import GARCH, FixedVariance\n",
    "\n",
    "mod = HARX(vix, lags=[1, 5, 22])\n",
    "res = mod.fit()\n",
    "print(res.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initial Volatility Model Estimation\n",
    "Using the previously estimated residuals, a volatility model can be estimated using a `ZeroMean`. In this example, a GJR-GARCH process is used for the variance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "vol_mod = ZeroMean(res.resid.dropna(), volatility=GARCH(p=1, o=1, q=1))\n",
    "vol_res = vol_mod.fit(disp=\"off\")\n",
    "print(vol_res.summary())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ax = vol_res.plot(\"D\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Re-estimating the mean with a ``FixedVariance``\n",
    "The `FixedVariance` requires that the variance is provided when initializing the object.  The variance provided should have the same shape as the original data.  Since the variance estimated from the GJR-GARCH model is missing the first 22 observations due to the HAR lags, we simply fill these with 1.  These values will not be used to estimate the model, and so the value is not important. \n",
    "\n",
    "The summary shows that there is a single parameter, ``scale``, which is close to 1. The mean parameters\n",
    "have changed which reflects the GLS-like weighting that this re-estimation imposes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "variance = np.empty_like(vix)\n",
    "variance.fill(1.0)\n",
    "variance[22:] = vol_res.conditional_volatility**2.0\n",
    "fv = FixedVariance(variance)\n",
    "mod = HARX(vix, lags=[1, 5, 22], volatility=fv)\n",
    "res = mod.fit()\n",
    "print(res.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Zig-Zag estimation\n",
    "A small repetitions of the previous two steps can be used to implement a so-called zig-zag estimation strategy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(5):\n",
    "    print(i)\n",
    "    vol_mod = ZeroMean(res.resid.dropna(), volatility=GARCH(p=1, o=1, q=1))\n",
    "    vol_res = vol_mod.fit(disp=\"off\")\n",
    "    variance[22:] = vol_res.conditional_volatility**2.0\n",
    "    fv = FixedVariance(variance, unit_scale=True)\n",
    "    mod = HARX(vix, lags=[1, 5, 22], volatility=fv)\n",
    "    res = mod.fit(disp=\"off\")\n",
    "print(res.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Direct Estimation\n",
    "This model can be directly estimated.  The results are provided for comparison to the previous \n",
    "``FixedVariance`` estimates of the mean parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "mod = HARX(vix, lags=[1, 5, 22], volatility=GARCH(1, 1, 1))\n",
    "res = mod.fit(disp=\"off\")\n",
    "print(res.summary())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
